/**
 * 报表设计公司(2011)
 */
package com.reportgear.designer.action;

import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.HashMap;
import java.util.Map;

import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

import net.abbp.report.designer.action.IAction;

/**
 * 抽象操作
 * 
 * @version 1.0 2011-3-24
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ANNCSR 2.0
 */
public abstract class AbstractAction implements IAction {
	// 建立按钮ToolTipText
	public static String createButtonToolTipText(IAction action) {
		final StringBuffer sb = new StringBuffer();

		final String str = (String) action.getValue(Action.NAME);
		if (str.lastIndexOf("(") != -1) {
			sb.append(str.substring(0, str.lastIndexOf("(")));
		} else {
			sb.append(str);
		}
		final KeyStroke keyStroke = (KeyStroke) action.getValue("AcceleratorKey");
		if (keyStroke != null) {
			sb.append(" (");
			sb.append(KeyEvent.getKeyModifiersText(keyStroke.getModifiers()));
			sb.append("+");
			sb.append(KeyEvent.getKeyText(keyStroke.getKeyCode()));
			sb.append(")");
		}

		return sb.toString();
	}

	// 属性观察支持对象
	private PropertyChangeSupport changeSupport;
	// 包含对象
	private transient Map<String, Object> componentMap;
	// 是否有效
	private boolean enabled = true;

	// 是否为Toogle按钮
	private boolean isToggleButton = false;

	public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
		if (changeSupport == null) {
			changeSupport = new PropertyChangeSupport(this);
		}

		changeSupport.addPropertyChangeListener(listener);
	}

	/**
	 * 添加到工具条
	 * 
	 * @param toolbar
	 *            目标工具条
	 * @param group
	 *            所属按钮组
	 */
	public void addToJToolBar(JToolBar toolbar, Map<String, ButtonGroup> group) {
		final JComponent c = createToolBarComponent();
		if ((this instanceof RadioAction) && (c instanceof AbstractButton)) {
			final RadioAction ra = (RadioAction) this;
			final String str = ra.getGroupName();
			ButtonGroup btnGroup = group.get(str);
			if (btnGroup == null) {
				btnGroup = new ButtonGroup();
				group.put(str, btnGroup);
			}
			btnGroup.add((AbstractButton) c);
		}

		toolbar.add(c);
	}

	public JComponent createToolBarComponent() {
		Object button = getValue(JButton.class.getName());
		if ((button == null) || !(button instanceof AbstractButton)) {
			AbstractButton newButton = null;
			if (isToggleButton) {
				newButton = new JToggleButton();
			} else {
				newButton = new JButton();
			}
			final Integer mnemonicKey = (Integer) getValue(Action.MNEMONIC_KEY);
			if (mnemonicKey != null) {
				newButton.setMnemonic(mnemonicKey.intValue());
			}
			newButton.setIcon((Icon) getValue(Action.SMALL_ICON));
			newButton.addActionListener(this);

			putValue(JButton.class.getName(), newButton);
			newButton.setText("");
			newButton.setEnabled(isEnabled());
			newButton.setToolTipText(AbstractAction.createButtonToolTipText(this));

			button = newButton;
		}
		return (JComponent) button;
	}

	/**
	 * 通知属性改变
	 * 
	 * @param propertyName
	 *            属性名称
	 * @param oldValue
	 *            原值
	 * @param newValue
	 *            新值
	 */
	protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
		if ((changeSupport == null) || ((oldValue != null) && (newValue != null) && (oldValue.equals(newValue)))) {
			return;
		}
		changeSupport.firePropertyChange(propertyName, oldValue, newValue);
	}

	public KeyStroke getAccelerator() {
		return (KeyStroke) getValue(Action.ACCELERATOR_KEY);
	}

	public char getMnemonic() {
		final Integer obj = (Integer) getValue(Action.MNEMONIC_KEY);
		return (obj == null) ? '\0' : (char) obj.intValue();
	}

	public String getName() {
		return (String) getValue(Action.NAME);
	}

	public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
		if (changeSupport == null) {
			return new PropertyChangeListener[0];
		}

		return changeSupport.getPropertyChangeListeners();
	}

	public Icon getSmallIcon() {
		return (Icon) getValue(Action.SMALL_ICON);
	}

	public Object getValue(String key) {
		if (componentMap == null) {
			return null;
		}

		return componentMap.get(key);
	}

	public boolean isEnabled() {
		return enabled;
	}

	public void putValue(String key, Object value) {
		if (componentMap == null) {
			componentMap = new HashMap<String, Object>();
		}

		componentMap.put(key, value);
	}

	public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
		if (changeSupport == null) {
			return;
		}

		changeSupport.removePropertyChangeListener(listener);
	}

	public void setAccelerator(KeyStroke acceleratorKey) {
		putValue(Action.ACCELERATOR_KEY, acceleratorKey);
	}

	public void setEnabled(boolean enabled) {
		if (this.enabled == enabled) {
			return;
		}

		this.enabled = enabled;
		for (final Object c : componentMap.values()) {
			if (c instanceof JComponent) {
				((JComponent) c).setEnabled(this.enabled);
			}
		}
	}

	public void setMnemonic(char mnemonic) {
		putValue(Action.MNEMONIC_KEY, new Integer(mnemonic));
	}

	public void setName(String name) {
		putValue(Action.NAME, name);
	}

	public void setSmallIcon(Icon smallIcon) {
		putValue(Action.SMALL_ICON, smallIcon);
	}

	public void setToggleButton(boolean isToggleButton) {
		this.isToggleButton = isToggleButton;
	}
}